package com.cqhgcloud.monarch.organ.config;

import java.io.IOException;
import java.io.PrintWriter;
import java.util.HashMap;
import java.util.Map;

import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.access.AccessDeniedException;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.DisabledException;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.core.userdetails.UsernameNotFoundException;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.security.web.access.AccessDeniedHandler;

import com.cqhgcloud.monarch.organ.service.SysUserService;
import com.cqhgcloud.monarch.organ.service.impl.LoginServiceImpl;
import com.fasterxml.jackson.databind.ObjectMapper;

import lombok.AllArgsConstructor;

/**
 * Spring Security 安全配置
 * @author weimeilayer
 * @date 2020年1月31日 下午3:49:27
 */
@Configuration
@EnableWebSecurity
@AllArgsConstructor
public class WebSecurity extends WebSecurityConfigurerAdapter {
	
	private ObjectMapper objectMapper;
	
	private SysUserService sysUserService;
	
	private LoginServiceImpl loginservice;
	
	//private final RedisTemplate redisTemplate;
	
	@Override
	protected void configure(HttpSecurity http) throws Exception {
		http.headers().frameOptions().disable();
		// 开启跨域访问
		http.cors().disable();
		// 开启模拟请求
		http.csrf().disable();
		// 禁用缓存
		http.authorizeRequests()
				.antMatchers("/actuator/**","/v2/api-docs/**","/user/info/**","/social/info/**","/webjars/**","/swagger-resources/**","/css/**","/fonts/**","/favicon.ico","/img/**", "/js/**","/upload/**","/doc.html/**","/swagger-ui.html/**","/index","/login","/upload")
				.permitAll()// 配置权限
				.anyRequest().authenticated()// 任意请求需要登录
				.and()
				// 开启formLogin默认配置
				.formLogin()
				// 请求时未登录跳转接口
				.loginPage("/login").loginProcessingUrl("/login")// post登录接口，登录验证由系统实现
				.successHandler((request, response, authentication) -> {
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("code", 200);
					map.put("message", "登录成功");
					map.put("data", sysUserService.finSysUserByuserAccount(authentication.getName()));
					//redisTemplate.opsForHash().put(authentication.getDetails(), authentication.getPrincipal(),authentication.getName());
					response.setContentType("application/json;charset=utf-8");
					PrintWriter out = response.getWriter();
					out.write(objectMapper.writeValueAsString(map));
					out.flush();
					out.close();
				})
				// 登录失败，返回json
				.failureHandler((request, response, ex) -> {
					response.setContentType("application/json;charset=utf-8");
					response.setStatus(HttpServletResponse.SC_UNAUTHORIZED);
					PrintWriter out = response.getWriter();
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("code", 401);
					if (ex instanceof UsernameNotFoundException || ex instanceof BadCredentialsException) {
						map.put("message", "用户名或密码错误");
					} else if (ex instanceof DisabledException) {
						map.put("message", "账户被禁用");
					} else {
						map.put("message", "登录失败!");
					}
					out.write(objectMapper.writeValueAsString(map));
					out.flush();
					out.close();
				}).and()
				// 退出成功，返回json
				.logout().logoutSuccessHandler((request, response, authentication) -> {
					Map<String, Object> map = new HashMap<String, Object>();
					map.put("code", 200);
					map.put("message", "退出成功");
					map.put("data","");
					response.setContentType("application/json;charset=utf-8");
					PrintWriter out = response.getWriter();
					out.write(objectMapper.writeValueAsString(map));
					out.flush();
					out.close();//Authorization Bearer db588b66-2eb5-4464-acd0-5fd22d857260
				}).permitAll().invalidateHttpSession(true).deleteCookies("JSESSIONID")
				/* 处理异常请求 */
				.and().exceptionHandling().accessDeniedHandler(accessDeniedHandler())
				.authenticationEntryPoint(new CustomAuthenticationEntryPoint());
	}

	@Autowired
	public void configureGlobal(AuthenticationManagerBuilder auth) throws Exception {
		auth.userDetailsService(loginservice).passwordEncoder(new BCryptPasswordEncoder());
	}

	@Bean
	public AccessDeniedHandler accessDeniedHandler() {
		return new AccessDeniedHandler() {
			/**
			 * 处理异常请求
			 */
			@Override
			public void handle(HttpServletRequest request, HttpServletResponse response,
					AccessDeniedException accessDeniedException) throws IOException, ServletException {
				response.setContentType("application/json;charset=utf-8");
				PrintWriter out = response.getWriter();
				out.write("{\"code\":\"401\",\"msg\":\"请求异常\"}");
				out.flush();
				out.close();
			}
		};
	}
}
